from utils.response import APIResponse
from rest_framework.generics import CreateAPIView
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from urllib.parse import urlencode
from urllib.request import urlopen
import json
from django.core.mail import send_mail
from .serializer import UserModelSerializer
from .models import User
from django.conf import settings
from celery_task.sms_task import send_sms
from django_redis import get_redis_connection
import re
from itsdangerous import TimedJSONWebSignatureSerializer, BadData


class CaptchaAPIView(APIView):
    """验证码"""

    def get(self, request):
        """接受客户端提交的验证码相关信息"""
        params = {
            "aid": settings.TENCENT_CAPTCHA.get("APPID"),
            "AppSecretKey": settings.TENCENT_CAPTCHA.get("App_Secret_Key"),
            "Ticket": request.query_params.get("ticket"),
            "Randstr": request.query_params.get("randstr"),
            # request._request表示获取django框架的request对象
            "UserIP": request._request.META.get("REMOTE_ADDR")
        }
        # 把字典数据转换成地址栏的查询字符串格式
        params = urlencode(params)
        url = settings.TENCENT_CAPTCHA.get("GATEWAY")

        f = urlopen("%s?%s" % (url, params))

        # f.read() 读取响应信息
        content = f.read()
        res = json.loads(content)
        if int(res.get("response")) == 1:
            # 验证成功
            return APIResponse(code=1)
        else:
            # 验证失败
            return APIResponse(code=0, msg='验证失败')


class UserAPIView(CreateAPIView):
    """用户注册视图接口"""
    queryset = User.objects.all()
    serializer_class = UserModelSerializer


class SMSAPIView(APIView):
    """短信api接口"""

    def get(self, request, mobile):
        redis_conn = get_redis_connection('sms_code')

        # 限制用户60s内发送一条短信
        ret = redis_conn.get('interval_%s' % mobile)
        if ret is not None:
            # 如果ret有值，表示60s内用户曾经发送短信，不能让用户频繁发送短信
            return APIResponse(code=0, msg='对不起，短信发送过于频繁！')
        # 生成验证码
        from libs.YanPian import get_code, send_single_sms
        sms_code = get_code()

        # 保存验证码和手机到redis里面
        # 开启管道和事物
        pipe = redis_conn.pipeline()
        pipe.multi()
        redis_conn.setex("sms_%s" % mobile, settings.SMS_EXPIRE_TIME, sms_code)
        redis_conn.setex('interval_%s' % mobile, settings.SMS_INTERVAL_TIME, "_")  # 发送短信的间隔
        pipe.execute()
        # 异步发送短信
        result = send_single_sms(mobile, sms_code)
        # send_sms.delay(mobile=mobile,sms_code=sms_code)

        if result:
            return APIResponse(code=1, msg='验证码发送成功,请留意您的手机短信')
        else:
            return APIResponse(code=0, msg='验证码发送失败')


class MobileAPIView(APIView):
    """校验手机号视图接口"""
    def get(self, request, mobile):
        mobile = User.objects.filter(mobile=mobile).first()
        if not mobile:
            return APIResponse(msg='ok')
        return APIResponse(code=0, msg='手机号码已被注册！')


class FindPasswordAPIView(APIView):
    """用户找回密码视图接口"""

    def get(self, request, *args, **kwargs):

        """发送邮件"""
        email = request.query_params.get('email')

        if not re.match("^\w+@\w+\.\w+$", email):
            return APIResponse(code=0, msg='邮箱格式不正确')
        user = User.objects.filter(email=email).first()
        if not user:
            return APIResponse(code=0, msg='您的邮箱还没有注册,请重新确认')
        # 使用itsdangerous对链接中的数据进行加密
        serializer = TimedJSONWebSignatureSerializer(secret_key=settings.SECRET_KEY,
                                                     expires_in=settings.EMAIL_EXPIRE_TIME)

        token = serializer.dumps({"email": email}).decode()

        url = settings.CLIENT_HOST + "/reset_password?token=%s" % token

        send_mail(subject="【西红柿】找回密码", message="这是很重要的内容",
                  html_message='尊敬的%s,您好!<br><br>您在西红柿网申请了找回密码,请点击 < a href = "%s"target = "_blank" > 重置密码 < / a > 进行密码修改操作. < br > < br > 如果不是您本人的操作, 请忽略本次邮件!' % (
                      user.username, url), from_email=settings.EMAIL_FROM, recipient_list=[email])

        return APIResponse()


class CheckTokenAPIView(APIView):
    """校验token视图接口"""
    def get(self, request):
        token_string = request.query_params.get("token")
        serializer = TimedJSONWebSignatureSerializer(secret_key=settings.SECRET_KEY,
                                                     expires_in=settings.EMAIL_EXPIRE_TIME)
        try:
            token = serializer.loads(token_string)
        except BadData:

            return Response({"detail": "对不起,当前链接地址不存在或者已过期!"}, status=status.HTTP_400_BAD_REQUEST)

        return Response({"email": token.get("email")})


class ResetPasswordAPIView(APIView):
    """用户重置密码视图接口"""
    def put(self, request):
        token_string = request.query_params.get("token")

        serializer = TimedJSONWebSignatureSerializer(secret_key=settings.SECRET_KEY,
                                                     expires_in=settings.EMAIL_EXPIRE_TIME)

        try:
            token = serializer.loads(token_string)

        except BadData:

            return Response({"detail": "对不起,当前链接地址不存在或者已过期!"}, status=status.HTTP_400_BAD_REQUEST)

        password = request.data.get("password")
        password2 = request.data.get("password2")

        if password != password2:
            return Response({"detail": "密码和确认密码不一致!"}, status=status.HTTP_400_BAD_REQUEST)

        user = User.objects.get(email=token.get("email"))
        user.set_password(password)
        user.save()

        return Response({"detail": "修改密码成功!"})
